  def map_all_tables (destination_table,create_table_option,source_connection,destination_connection)
      all_tables = source_connection.tables
      options = {:create_destination_table=>create_table_option,:destination=>destination_connection,:source=>destination_connection,all_tables=>["#{destination_table}"]}    
      load_data(options)
  end
  
  
  # This method will load only selected columns of the table.
  # The columns can be specified explicitely, position wise or numerically as well.  
  def load_selected_data(options={})
      get_columns(options,"by_selection")
  end  


  # This method woll load only selected columns of the table.
  # In this case columns are selected by the constraint name.
  def load_data_by_constraint(options={})     
      get_columns(options,"by constraint")
  end  

  # In the selective mapped loading; based on the constraints or the numbers this method will extract the columns.
  def get_columns(options,criteria)
      destination_connection = options[:destination]
      source_connection= options[:source]
      constraints = options[:constraint_names] 
      options.each{|source_options,destination_table|
          if ![constraints,source_connection,destination_connection,true,false].include?destination_table 
              source_options.each{|table_names,column_names|
                  table_names = [table_names] if !table_names.respond_to?"join"
                  selected_data = ""
                  for single_table in table_names
                      all_columns = get_column_list(source_connection,single_table)
                      if criteria == "by selection"
                          required_columns = get_required_columns(all_columns,column_names,"",source_connection)  
                      elsif criteria == "by constraint"
                          for constraint in constraints.to_s
                              required_columns = get_columns_by_constraint(constraint,single_table,source_connection)
                          end    
                      end      
                      if single_table == table_names.first
                          check_table_existance_and_create_if_absent(destination_connection,destination_table,options[:create_destination_table],single_table,source_connection,required_columns)
                      end    
                      execute_partial_column_loading(required_columns,single_table,source_connection,destination_connection,destination_table)  
                  end    
              }
          end    
      }  
  end


  # This is the loading where multiple tables can be mapped to a single table in destination database and loaded.
  def load_data(options={})
      destination_connection = options[:destination]
      source_connection= options[:source]
      options.each{|source_table_array,destination_table|
          if ![source_connection,destination_connection,true,false].include?destination_table 
              for source_table in source_table_array  
                  merge_the_complete_tables_data(source_table,source_connection,destination_connection,destination_table,options[:create_destination_table])              
              end
          end      
      }
  end  


  
  # This method checks if the table is existing in the database. If it does not and if create_table_in_destination is true then it will create that table.  
  def check_table_existance_and_create_if_absent(destination_connection,destination_table,create_table_in_destination,source_table,source_connection,column_names)
      if !(destination_connection.tables.include?destination_table) 
          if create_table_in_destination
              query_string = "CREATE TABLE #{destination_table} ("  
              column_names = get_column_list(source_connection,source_table) if !column_names
              for column_name in column_names
                  col_specs = get_the_col_spec_for_single_col(column_name,source_table,source_connection)
                  column_name = remove_all_the_invalid_chars(column_name)
                  query_string << "#{column_name} #{col_specs}"
                  query_string << "," if column_name != column_names.last
              end
              query_string << ")"
              destination_connection.execute("#{query_string}")
          else
              puts "The destination table does not exist. Please set the create_destination_table option in your ETL script as true so that RExTraL can create it for you."
          end    
      end  
  end      



  # This method is for merging the the two tables' data for all the columns.
  # false is being sent to ensure that target table if not found will be created for all the columns and not for some particular columns only.
  def merge_the_complete_tables_data(source_table,source_connection,destination_connection,destination_table,create_table_in_destination)            
      all_data = source_connection.execute("select * from #{source_table}")
      check_table_existance_and_create_if_absent(destination_connection,destination_table,create_table_in_destination,source_table,source_connection,false)
      for single_record in all_data
          value_string = ""
          single_record.each{|single_value|
              single_value = " " if [nil,""].include?(single_value)
              value_string = value_string +"\""+(single_value.chomp)+"\"," 
          }
          value_string[(value_string.length-1)] = ""
          destination_connection.execute("INSERT INTO #{destination_table} VALUES (#{value_string})")
      end
  end  


